"""
# -*- coding: utf-8 -*-
# @Time    : 2023/5/19 19:51
# @Author  : 王摇摆
# @FileName: Visual.py
# @Software: PyCharm
# @Blog    ：https://blog.csdn.net/weixin_44943389?type=blog
"""
# -*- coding: utf-8 -*-

from matplotlib.colors import LinearSegmentedColormap
from sklearn.datasets import make_classification
from sklearn import tree
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

'''
# 获取数据，使用模型
'''
# 拿到分类数据
X, y = make_classification(n_features=2, n_informative=2, n_redundant=0, n_samples=100, n_classes=2, random_state=0)
y[y == 0] = -1

# 决策树分类器
# clf = tree.DecisionTreeClassifier(m) # 先拿到模型
# clf = tree.DecisionTreeClassifier()
clf = tree.DecisionTreeClassifier(max_depth=3, min_samples_leaf=5) # 对决策树进行正则化，防止过拟合现象的发生
clf = clf.fit(X, y) # 人工数据训练分类器，将分类器先训练好

'''
# 输出结果可视化
'''
# 指定中文字体文件的路径
font_path = 'C:\Windows\Fonts\simkai.ttf'
# 加载中文字体
font = FontProperties(fname=font_path)

plt.rcParams['font.sans-serif'] = ['simkai']  # 选择一个本地的支持中文的字体
fig, ax = plt.subplots()
ax.set_facecolor('#f8f9fa')

x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5 # 确保绘制的决策边界图包含所有样本点，并留出一定的边界空间
y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
xx, yy = np.meshgrid(np.arange(x_min, x_max, .05), np.arange(y_min, y_max, .05))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()]) # 对网格中的点分类预测
Z = Z.reshape(xx.shape)
clist = ['#ffadad', '#8ecae6']
newcmp = LinearSegmentedColormap.from_list('point_color', clist)
plt.pcolormesh(xx, yy, Z, cmap=newcmp) # 绘制决策边界和区域并填充颜色
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())

x1 = X[y == -1][:, 0]
y1 = X[y == -1][:, 1]
x2 = X[y == 1][:, 0]
y2 = X[y == 1][:, 1]
p1 = plt.scatter(x1, y1, c='#e63946', marker='o', s=20)
p2 = plt.scatter(x2, y2, c='#457b9d', marker='x', s=20)

ax.set_title('决策树分类(正则化)', color='#264653', fontproperties=font, fontsize=16)
ax.set_xlabel('X1', color='#264653')
ax.set_ylabel('X2', color='#264653')
ax.tick_params(labelcolor='#264653')
plt.legend([p1, p2], ["-EXP1", "EXP1"], loc="upper left")
plt.show()
